#include "db/DBManager.hh"

#include "common/stl.h"
#include <boost/algorithm/string.hpp> // strlower


DBManager::DBManager()
{
    std::cout << "establishing connection" << std::endl;

    // establishing a connection to the DB
    // TODO: read username / password from a configuration file
    // could replace to a lastconnection type (only when needed)
    _c = new pqxx::connection("dbname=rods user=zermingore");

    if (_c->is_open())
        std::cout << "Connection established to " << _c->dbname() << std::endl;
    else
    {
        std::cerr << "Connection failed !" << std::endl;
        // fall-back to solo mode or exit
        return;
    }

    // need to read user's input to authentication
    this->init(0, NULL);
}

DBManager::~DBManager()
{
	// close connection if needed
}


// mv to src/db/{users|account}
// fill in database log if we're running a server version
//   or client with debug flags ?
bool DBManager::authenticate(std::string login, std::string password)
{
    try
    {
        // Allowing user to connect
        pqxx::work txn(*_c, "login_transaction");
        pqxx::result r = txn.exec("SELECT * FROM rods.USERS WHERE login=" + txn.quote(login));

        // we know a login is unique so there *MUST* be 1 match, at most
        if (r.size() != 1)
        {
            std::cerr << "Login <" << login << "> not found" << r.size() << std::endl;
            return false;
        }

        if (password != r[0]["password"].c_str())
        {
            // could add 'Hint: caps-lock is active'
            // for a safer identification in case of wrong login || password,
            //   we could throw the same error message
            std::cerr << "Incorrect Password" << std::endl;
            return false;
        }

        // updating last connection time
        txn.exec("UPDATE rods.USERS SET last_connection=NOW() WHERE login=" + txn.quote(login));
        txn.commit();

        std::cout << "Welcome, " + login << std::endl;

        return true;
    }

    catch (...)
    {
        std::cerr << "Not commited" << std::endl;
    }

    return false;
}


// sandbox function
void DBManager::init(int, char *argv[])
{
    // Allowing user to connect
//    pqxx::work txn(*_c, "tst_transaction");
//    pqxx::result r = txn.exec("SELECT * FROM rods.USERS");
//
//    // Here, we're using iterators: slightly slower, safer
//    for (pqxx::result::const_iterator it = r.begin(); it != r.end(); ++it)
//    {
//        //for (int j = 0; r[i][j]; ++j)
//            std::cout << it["login"] << std::endl;
//
//        std::cout << std::endl << "\t---" << std::endl;
//    }
//
//    int id = r[0][0].as<int>();
//    std::cout << "Updating gun #" << id << std::endl;
//
//    txn.exec("UPDATE rods.GUNS SET durability=80 WHERE id_guns = " + txn.quote(id));
//    txn.commit();


    // shd rly forbid uppercase ?
    std::string login = "Zermingore";
    boost::algorithm::to_lower(login);
    if (this->authenticate(login, "tst"))
        return;
}


bool DBManager::doTransaction()
{
	try
	{
	   	pqxx::connection _c ("dbname=rods.db user=usr");
		pqxx::work txn(_c, "tst_transaction");

		txn.commit();

		return true;
	}

	catch (...)
	{
        std::cerr << "not committed" << std::endl;
	}

	return false;
}
